﻿using Contract;
using Newtonsoft.Json;
using SocketMessaging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using TcpServer.RSA;
using TcpServer.Tool;
using Tool;

namespace TcpServer
{
    class Program
    {

        //线程安全的字典
        static ConcurrentDictionary<int, Packet> dic = new ConcurrentDictionary<int, Packet>();

        static ConcurrentDictionary<int, Connection> connectionMap = new ConcurrentDictionary<int, Connection>();

        static Dictionary<string, string> commandMap;

        private Program()
        {
            commandMap = new Dictionary<string, string>();

            commandMap.Add("send_key_secret", "TcpServer.SocketCommandImpl.SendKeySecret");

            commandMap.Add("receive_file", "TcpServer.SocketCommandImpl.ReceiveFile");

            commandMap.Add("notice_online", "TcpServer.SocketCommandImpl.NoticeFriendOnline");
        }

        static void Main(string[] args)
        {
            new Program().ReceiveMsg();
        }


        private static void TcpServer_Connected(object sender, ConnectionEventArgs e)
        {
            e.Connection.SetMode(MessageMode.DelimiterBound);
            e.Connection.ReceivedMessage += Connection_ReceivedMessage;
            e.Connection.Disconnected += Connection_Disconnected;

            //  e.Connection.ReceivedRaw += ReceivedRaw;



            Packet packet = new Packet();

            packet.fd = e.Connection.Id;

           

            // dic.TryAdd(e.Connection.Id, packet);

            connectionMap.TryAdd(e.Connection.Id, e.Connection);

            var tcpServer = sender as SocketMessaging.Server.TcpServer;
            

            string privateKey = RSAScrect.PRIVATE_KEY ;

            ReceiveData<string> receive = new ReceiveData<string>("send_secrat", 1, privateKey);

            e.Connection.Send(JsonConvert.SerializeObject(receive));

        }

        private static void Connection_Disconnected(object sender, EventArgs e)
        {
            var disconnectedClient = sender as Connection;
          

            Packet packet;

            dic.Remove(disconnectedClient.Id, out packet);

            Connection connection;

            connectionMap.Remove(disconnectedClient.Id, out connection);

            Packet picketData = new Packet();

            picketData.fd = disconnectedClient.Id;

            picketData.userName = packet.userName;

            ReceiveData<Packet> data = new ReceiveData<Packet>("down", 1, picketData);

            var otherClients = StaticProperties.server.Connections.Except(new[] { disconnectedClient });
            try
            {
                // 通知下线
                foreach (var client in otherClients)
                {
                    Console.WriteLine($"#{client.Id}通知下线.");

                    if (client.IsConnected)
                    {
                        client.Send(JsonConvert.SerializeObject(data));
                    }

                }
            } catch
            {
                Console.WriteLine("连接错误");
            }

            Console.WriteLine($"#{disconnectedClient.Id} 下线");
        }

        private static void Connection_ReceivedMessage(object sender, EventArgs e)
        {
            var connection = sender as Connection;


            var message = connection.ReceiveMessageString();

            Console.WriteLine(message);

            if (message == null)
            {
                return;
            }

            try
            {

                ReceiveData<object> receiveData = JsonConvert.DeserializeObject<ReceiveData<object>>(message);

                string cmdClassName;

                if (!commandMap.TryGetValue(receiveData.cmd, out cmdClassName))
                {
                    throw new Exception($"没有找到#{receiveData.cmd}");
                }

                Type type = Type.GetType(cmdClassName);

                object[] constructParms = new object[] { connectionMap, dic};

                ISocketCommand command = (ISocketCommand)Activator.CreateInstance(type, constructParms);

                command.CallCommand(receiveData, connection);
            
            }
            catch (Exception ex)
            {
                Console.WriteLine("出现异常：" + ex.Message);
            }

          //  var otherClients = StaticProperties.server.Connections.Except(new[] { connection });
            //foreach (var client in otherClients)
            //{
            //    client.Send($"#{connection.Id}: {message}");
            //}

            Console.WriteLine($"#{connection.Id}: {message}");

        }


        /// <summary>
        /// 接收客户端发来的数据
        /// </summary>
        /// <param name="connId">每个客户的会话ID</param>
        /// <param name="bytes">缓冲区数据</param>
        /// <returns></returns>
        private bool OnReceive(IntPtr connId, byte[] bytes)
        {
            
            return true;
        }


        
        public void ReceiveMsg()
        {

            // TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9898);

            string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + "word.ini";

            ReadFile instance = ReadFile.getInstance(path);

            string port;

            bool res = instance.getDataByKey("port", out port);

            if (!res)
            {
                throw new Exception("找不到"+ path+"配置文件");
            }


            StaticProperties.server = new SocketMessaging.Server.TcpServer();

            StaticProperties.server.Connected += TcpServer_Connected;

            StaticProperties.server.Start(ushort.Parse(port));


            //使用命令关闭
            while (true)
            {
                if (Console.ReadLine().ToLower() == "exit")
                {
                    return;
                }
            }
        }
    }

}
